--
ModSecurity
Overview
ModSecurity is an open-source Web Application Firewall (WAF) engine that inspects HTTP requests and responses and enforces rules to detect or block common web attacks (for example, SQL injection and cross-site scripting). It is typically deployed as a module or connector alongside a web server or reverse proxy and is most effective when paired with a maintained rule set such as the OWASP Core Rule Set (CRS). (OWASP Foundation)
History
- ModSecurity began as an Apache HTTP Server module and later evolved to support additional platforms. (OWASP Foundation)
- ModSecurity v3 introduced a connector-based architecture that separates the core engine (
libmodsecurity) from web-server-specific connectors. (GitHub)
Adoption
Commonly used in:
- Internet-facing sites and APIs needing additional request/response inspection beyond baseline server controls
- Reverse-proxy and CDN-adjacent deployments where traffic is centralized
- Kubernetes ingress environments that support ModSecurity integrations (kubernetes.github.io)
Maintainer
Maintained by the OWASP ModSecurity project and community. (OWASP Foundation)
Best when to use
- You need rules-based detection and blocking for common web attack patterns
- You can start in detection-only mode and tune before enforcing blocks
- You want standardized baseline protection via OWASP CRS with anomaly scoring and tuning controls (OWASP Foundation)
- You have the operational capacity to maintain rule updates, exclusions, and monitoring
Not suitable when
- You cannot tolerate any false positives and do not have time to tune rules
- Your architecture cannot support safe rollout controls (staging, canary, detection-only period)
- You are looking for a replacement for secure coding, input validation, authentication hardening, or patch management
Compatibility notes
- ModSecurity v2 is commonly deployed as an Apache module on many distributions.
- ModSecurity v3 uses
libmodsecurityplus a web-server connector (for example, Apache connector or NGINX connector). (GitHub) - Packaging varies by OS and distribution; verify what you have installed and which major version you are running before following a guide.
A WAF can block legitimate traffic if rules or thresholds are too strict. Always roll out in DetectionOnly first, review logs, then move to blocking with staged changes.
How it works
ModSecurity evaluates transactions (request headers/body, response headers/body) against a ruleset. Rules can:
- Log events (audit)
- Add tags and variables
- Increase anomaly scores
- Deny or redirect requests
With OWASP CRS, decisions are commonly made using anomaly scoring: rules add points to a transaction score, and actions are taken when a threshold is exceeded. (CRS Project)
Installation and deployment models
ModSecurity is rarely “installed and done”; it’s deployed as part of a web server stack. Identify your deployment model first.
| Model | Typical components | Notes |
|---|---|---|
| - | -- | |
| Apache | ModSecurity module (v2) or libmodsecurity + Apache connector (v3) | Often simplest via distro packages for v2; v3 requires connector. (GitHub) |
| NGINX | libmodsecurity + NGINX connector | Commonly built/packaged separately; verify your distribution support. (DeepWiki) |
| IIS | Platform integration varies | Verify supported version and deployment method for your environment. (GitHub) |
| Kubernetes ingress | Ingress controller integration | Typically enabled via controller configuration; validate supported features and logging paths. (kubernetes.github.io) |
Verify what is installed (read-only)
Apache
apachectl -M 2>/dev/null | grep -i security || true
apachectl -v
NGINX
nginx -V 2>&1 | tr ' ' '\n' | grep -i modsecurity || true
nginx -V 2>&1 | head -n 2
Locate ModSecurity configuration
Common paths vary by distro and version. Search safely:
sudo find /etc -maxdepth 3 -type f \( -iname "*modsecurity*" -o -iname "*owasp-crs*" -o -iname "crs-setup.conf*" \) 2>/dev/null | head
Core configuration concepts
Engine modes
ModSecurity generally runs in one of these modes:
| Mode | Setting | Effect |
|---|---|---|
| -- | -- | |
| Off | SecRuleEngine Off | No inspection |
| Detection-only | SecRuleEngine DetectionOnly | Inspects and logs, does not block |
| On (blocking) | SecRuleEngine On | Can block based on rules/actions |
Start with DetectionOnly, tune exclusions and thresholds, then enable blocking during a controlled rollout.
Audit logging
Audit logs are essential for tuning and incident response.
Typical settings include:
SecAuditEngine RelevantOnly(orOnfor full)SecAuditLogpathSecAuditLogPartsselection
Make sure the web server can write to the audit log path and that log rotation is configured by your OS tooling.
Using OWASP Core Rule Set (CRS)
OWASP CRS is a generic attack-detection rule set designed for ModSecurity and compatible WAF engines. (OWASP Foundation)
Key tuning controls
Common CRS tuning levers include:
- Anomaly thresholds (when to block)
- Paranoia level (how strict the rules are)
- Rule exclusions (disable or narrow rules for known-safe endpoints)
CRS typically uses anomaly scoring to accumulate signals across multiple rules and then make a decision. (CRS Project)
Enabling CRS in blocking mode without tuning can break logins, checkout flows, admin panels, and file uploads. Always validate critical user journeys before enforcing blocks.
Practical configuration patterns
Exact file names and include paths vary across OS distributions and packaging. The patterns below show intent and safe defaults, not distro-specific filenames.
Minimal baseline (DetectionOnly)
Example snippet:
# Engine mode: start safe
SecRuleEngine DetectionOnly
# Request body inspection is required for many WAF rules
SecRequestBodyAccess On
# Basic audit logging (ensure the path is writable)
SecAuditEngine RelevantOnly
SecAuditLog /var/log/modsecurity/audit.log
# Load rules (CRS and local rules)
Include /etc/modsecurity/crs/crs-setup.conf
Include /etc/modsecurity/crs/rules/*.conf
Include /etc/modsecurity/local-rules/*.conf
Move to blocking mode
After tuning (see Troubleshooting and Tuning), switch to:
SecRuleEngine On
Blocking mode can deny legitimate requests, including admin logins. Before switching to On, ensure you have:
- An out-of-band access method (console access, bastion, alternate auth path)
- A fast rollback plan (config revert + reload)
- Monitoring on 403/406/500 rates
Common operational tasks
Reload safely
Prefer config tests before reload.
Apache
sudo apachectl configtest
sudo systemctl reload apache2 2>/dev/null || sudo systemctl reload httpd
NGINX
sudo nginx -t
sudo systemctl reload nginx
Confirm WAF is evaluating requests
Use a harmless request that triggers logging (not necessarily blocking):
curl -i https://example.test/ -H 'User-Agent: waf-smoke-test'
Then check error and audit logs (paths vary):
sudo tail -n 50 /var/log/apache2/error.log 2>/dev/null || true
sudo tail -n 50 /var/log/nginx/error.log 2>/dev/null || true
sudo tail -n 50 /var/log/modsecurity/audit.log 2>/dev/null || true
Troubleshooting and tuning
Determine what triggered a block
Look for:
- Rule ID (for example,
id "9xxxxx") - Matched variable (
ARGS,REQUEST_HEADERS, etc.) - Message/tags
- Anomaly score and threshold (CRS)
Typical workflow:
- Find the event in the audit log around the timestamp.
- Identify the rule ID(s) and match data.
- Confirm whether it’s a true positive or false positive.
- Apply the smallest possible exclusion scoped to the affected endpoint/parameter.
Apply a scoped exclusion (example pattern)
Use narrowly scoped exclusions rather than disabling broad rule categories.
# Example: remove a rule for a specific endpoint only
SecRule REQUEST_URI "@beginsWith /api/v1/upload" \
"id:100001,phase:1,pass,nolog,ctl:ruleRemoveById=920273"
Avoid global ruleRemoveById without conditions. Global removals can create blind spots across the entire site.
Common sources of false positives
| Area | Why it triggers | Typical fixes |
|---|---|---|
| -- | - | |
| JSON APIs | High-entropy strings, nested JSON keys, encoded payloads | Ensure correct content-type handling; tune exclusions to specific parameters |
| Login forms | Credential patterns resemble attacks | Tune rule exclusions to login endpoint fields |
| File uploads | Multipart boundaries, file metadata | Validate upload rules and set size limits appropriately |
| Admin panels | Verbose query params and plugins | Increase threshold or scope exclusions for admin-only paths |
Performance issues
Signs:
- Increased request latency
- High CPU usage
- Large audit logs
- Timeouts on large request bodies
Mitigations:
- Use
RelevantOnlyaudit logging where appropriate - Apply request body size limits appropriate to your app
- Reduce paranoia level or tune specific noisy rules
- Prefer targeted exclusions over broad disabling
Security notes
A WAF reduces risk, but it does not replace patching, secure coding, authentication hardening, and least-privilege access controls.
Operational hardening:
- Run detection-only first and tune before enabling blocking.
- Keep rulesets updated (CRS updates matter as much as engine updates). (OWASP Foundation)
- Restrict administrative endpoints via network controls and strong authentication; do not rely on WAF rules alone.
- Monitor for rule update regressions with staging tests and canary rollout.
Quick reference
Engine modes
| Goal | Setting |
|---|---|
| - | -- |
| Disable WAF | SecRuleEngine Off |
| Observe and tune | SecRuleEngine DetectionOnly |
| Enforce blocks | SecRuleEngine On |
Read-only diagnostics
| Task | Command |
|---|---|
| -- | -- |
| Check Apache modules | apachectl -M | grep -i security |
| Check NGINX build flags | nginx -V 2>&1 | tr ' ' '\n' | grep -i modsecurity |
| Test Apache config | apachectl configtest |
| Test NGINX config | nginx -t |
| Tail common logs | tail -n 50 /var/log/modsecurity/audit.log |
Safe rollout checklist
- Enable
DetectionOnly - Confirm audit log collection
- Deploy CRS with conservative paranoia level and thresholds
- Tune false positives using scoped exclusions
- Switch to
Onduring controlled rollout with monitoring and rollback path